package com.tianxiao.faas.biz.service.corner;

import com.alibaba.fastjson.JSON;
import com.tianxiao.faas.api.param.corner.AiOrderParam;
import com.tianxiao.faas.common.constants.CommonConstants;
import com.tianxiao.faas.common.util.NamedThreadPools;
import com.tianxiao.faas.common.util.StringUtils;
import com.tianxiao.faas.mapper.dao.OrderHistoryModelMapper;
import com.tianxiao.faas.mapper.model.OrderHistoryModel;
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.net.Proxy;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class AiService {

    @Resource
    private OrderHistoryModelMapper orderHistoryModelMapper;

    final static Logger logger = LoggerFactory.getLogger(ShopService.class);

    private ExecutorService executorService = NamedThreadPools.newFixedThreadPool(50, "ai-executor");

    @Value("${ai.host}")
    private String aiHost;

    @Value("${ai.orderPath}")
    private String orderPath;

    private long timeout = 90;

    private Proxy proxy = Proxy.NO_PROXY;



    public OkHttpClient getOkHttpClient () {
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.connectTimeout(timeout, TimeUnit.SECONDS);
        client.writeTimeout(timeout, TimeUnit.SECONDS);
        client.readTimeout(timeout, TimeUnit.SECONDS);
        if (Objects.nonNull(proxy)) {
            client.proxy(proxy);
        }

        OkHttpClient okHttpClient = client.build();
        return okHttpClient;
    }

    public SseEmitter order(AiOrderParam aiOrderParam, Long userId) {
        SseEmitter sseEmitter = new SseEmitter(-1L);
        Map<String, String> map = new HashMap<>();
        map.put("shop_id", String.valueOf(aiOrderParam.getShopId()));
        map.put("user_requirement", aiOrderParam.getUserRequirement());
        final String[] stringBuilder = {""};
        long l = System.currentTimeMillis();
        streamChatCompletion(map, new EventSourceListener() {
            @Override
            public void onOpen(EventSource eventSource, Response response) {
                super.onOpen(eventSource, response);
            }
            @Override
            public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) {
                logger.info("response：" + data);
                if (data.equals("[end]")) {
                    complete(sseEmitter);
                    return;
                }
                if (data != null) {
                    if (!data.contains("\n\n") && data.contains("\n")){
                        data = data.replace("\n","\n\n");
                    }
                    stringBuilder[0] = data;
                    String encode = null;
                    try {
                        encode = URLEncoder.encode(data, "UTF-8");
                        send(sseEmitter, encode.replaceAll("\\+", "%20"));
                    } catch (Exception e) {
                        logger.error("order-error", e);
                    }

                }
            }

            @Override
            public void onClosed(EventSource eventSource) {
                OrderHistoryModel orderHistoryModel = new OrderHistoryModel();
                orderHistoryModel.setUserId(userId);
                orderHistoryModel.setShopId(aiOrderParam.getShopId());
                orderHistoryModel.setResult(stringBuilder[0]);
                orderHistoryModel.setType(CommonConstants.HISTORY_ORDER);
                orderHistoryModel.setUserRequirement(aiOrderParam.getUserRequirement());
                orderHistoryModel.setCreated(l);
                orderHistoryModel.setUpdated(l);
                orderHistoryModel.setDeleted(0);
                orderHistoryModel.setValueBox("");
                String shareId = Optional.ofNullable(aiOrderParam.getShareId())
                        .filter(StringUtils::isNotEmpty)
                        .orElseGet(() -> UUID.randomUUID().toString().replaceAll("-", ""));
                orderHistoryModel.setShareId(shareId);
                orderHistoryModelMapper.insertSelective(orderHistoryModel);
            }

            @Override
            public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) {
                super.onFailure(eventSource, t, response);
            }
        });
        return sseEmitter;
    }

    /**
     * 流式输出
     */
    public void streamChatCompletion(Object message,
                                     EventSourceListener eventSourceListener) {

        try {
            String apiUrl = aiHost + orderPath;
            EventSource.Factory factory = EventSources.createFactory(getOkHttpClient());
            String requestBody = JSON.toJSONString(message);


            Request request = new Request.Builder()
                    .url(apiUrl)
                    .post(RequestBody.create(MediaType.parse("application/json"),
                            requestBody))
                    .build();
            factory.newEventSource(request, eventSourceListener);

        } catch (Exception e) {
            logger.error("请求出错：{}", e);
        }
    }

    public void complete(SseEmitter sseEmitter) {

        try {
            sseEmitter.complete();
        } catch (Exception e) {

        }
    }

    public void send(SseEmitter sseEmitter, Object data) {

        try {
            sseEmitter.send(data);
        } catch (Exception e) {

        }
    }
}
